import { EventEmitter } from 'events'
import { roomConfig } from '../../config/room'
import { AppError } from '../../utils/AppError'
import { RedisService } from '../redis/RedisService'

export class RoomStateService extends EventEmitter {
  constructor(private readonly redis: RedisService) {
    super()
  }

  // 用户进入房间
  async userEnterRoom(roomId: string, userId: string) {
    const room = await this.redis.hgetall(`room:${roomId}:info`)
    if (!room || !room.id) {
      throw new AppError(404, '房间不存在')
    }

    // 检查房间状态
    if (room.status !== 'live' && !this.canEnterOffline(userId, room)) {
      throw new AppError(403, '房间未开播')
    }

    // 检查黑名单
    if (room.blockedUsers?.includes(userId)) {
      throw new AppError(403, '您已被房主禁止进入')
    }

    // 检查房间密码
    if (room.password && !(await this.checkRoomPassword(roomId, userId, room.password))) {
      throw new AppError(403, '需要密码才能进入')
    }

    // 更新在线状态
    const multi = this.redis.multi()
    multi.sadd(`room:${roomId}:online_users`, userId)
    multi.hincrby(`room:${roomId}:info`, 'currentViewers', 1)
    multi.hincrby(`room:${roomId}:info`, 'totalViewers', 1)

    // 更新用户状态
    multi.hset(`user:${userId}:state`, 'currentRoom', roomId)
    multi.hset(`user:${userId}:state`, 'enterTime', Date.now())

    await multi.exec()

    // 触发事件
    this.emit('user_enter', { roomId, userId })

    return true
  }

  // 用户离开房间
  async userLeaveRoom(roomId: string, userId: string) {
    const multi = this.redis.multi()
    multi.srem(`room:${roomId}:online_users`, userId)
    multi.hincrby(`room:${roomId}:info`, 'currentViewers', -1)
    multi.hdel(`user:${userId}:state`, 'currentRoom', 'enterTime')

    await multi.exec()

    // 触发事件
    this.emit('user_leave', { roomId, userId })

    return true
  }

  // 检查用户权限
  async checkPermission(roomId: string, userId: string, action: string) {
    const room = await this.redis.hgetall(`room:${roomId}:info`)
    if (!room || !room.id) {
      throw new AppError(404, '房间不存在')
    }

    // 房主拥有所有权限
    if (room.owner === userId) {
      return true
    }

    // 检查用户等级权限
    const user = await this.redis.hgetall(`user:${userId}:info`)
    const requiredLevel = roomConfig.permissions[action]?.minLevel || 0
    if (user.level < requiredLevel) {
      throw new AppError(403, '等级不足')
    }

    // 检查VIP权限
    const vipOnly = roomConfig.permissions[action]?.vipOnly || false
    if (vipOnly && !user.vipLevel) {
      throw new AppError(403, '需要VIP权限')
    }

    // 检查房管权限
    const isAdmin = await this.redis.sismember(`room:${roomId}:admins`, userId)
    const adminOnly = roomConfig.permissions[action]?.adminOnly || false
    if (adminOnly && !isAdmin) {
      throw new AppError(403, '需要房管权限')
    }

    // 检查禁言状态
    if (action === 'chat' || action === 'danmaku') {
      const muteKey = `room:${roomId}:mute:${userId}`
      const muteExpire = await this.redis.ttl(muteKey)
      if (muteExpire > 0) {
        throw new AppError(403, `您已被禁言，${muteExpire}秒后解除`)
      }
    }

    return true
  }

  // 获取房间在线用户
  async getOnlineUsers(roomId: string, page: number = 1, pageSize: number = 50) {
    const start = (page - 1) * pageSize
    const end = start + pageSize - 1

    const userIds = await this.redis.smembers(`room:${roomId}:online_users`)
    const total = userIds.length
    const pageIds = userIds.slice(start, end + 1)

    const users = await Promise.all(
      pageIds.map(async (userId) => {
        const user = await this.redis.hgetall(`user:${userId}:info`)
        const state = await this.redis.hgetall(`user:${userId}:state`)
        return {
          userId,
          nickname: user.nickname,
          avatar: user.avatar,
          level: parseInt(user.level),
          vipLevel: parseInt(user.vipLevel) || 0,
          enterTime: parseInt(state.enterTime),
        }
      })
    )

    return {
      total,
      users: users.sort((a, b) => b.enterTime - a.enterTime),
    }
  }

  // 设置房间管理员
  async setRoomAdmin(roomId: string, userId: string, targetId: string) {
    const room = await this.redis.hgetall(`room:${roomId}:info`)
    if (room.owner !== userId) {
      throw new AppError(403, '只有房主可以设置房管')
    }

    await this.redis.sadd(`room:${roomId}:admins`, targetId)
    this.emit('admin_added', { roomId, userId: targetId })

    return true
  }

  // 移除房间管理员
  async removeRoomAdmin(roomId: string, userId: string, targetId: string) {
    const room = await this.redis.hgetall(`room:${roomId}:info`)
    if (room.owner !== userId) {
      throw new AppError(403, '只有房主可以移除房管')
    }

    await this.redis.srem(`room:${roomId}:admins`, targetId)
    this.emit('admin_removed', { roomId, userId: targetId })

    return true
  }

  // 禁言用户
  async muteUser(roomId: string, userId: string, targetId: string, duration: number) {
    await this.checkPermission(roomId, userId, 'mute')

    const key = `room:${roomId}:mute:${targetId}`
    await this.redis.setex(key, duration, '1')

    this.emit('user_muted', { roomId, userId: targetId, duration })

    return true
  }

  // 私有方法：检查是否可以进入未开播房间
  private async canEnterOffline(userId: string, room: any): Promise<boolean> {
    // 房主可以进入
    if (userId === room.owner) return true

    // 房管可以进入
    const isAdmin = await this.redis.sismember(`room:${room.id}:admins`, userId)
    if (isAdmin) return true

    return false
  }

  // 私有方法：检查房间密码
  private async checkRoomPassword(
    roomId: string,
    userId: string,
    password: string
  ): Promise<boolean> {
    // 检查是否已通过验证
    const verified = await this.redis.sismember(`room:${roomId}:password_verified`, userId)
    if (verified) return true

    // 验证密码
    const key = `user:${userId}:room_password:${roomId}`
    const storedPassword = await this.redis.get(key)

    if (storedPassword === password) {
      await this.redis.sadd(`room:${roomId}:password_verified`, userId)
      return true
    }

    return false
  }
}
